#include <l3stdafx.h>
#include <l3base.h>

const xch * gbfkey = _T("@#wwsvc$%");
const xch * gsvcname = _T("Wiseman Server Service");
const xch * gsvcdisplay = _T("WISEWIRES Wiseman Server Service");
const xch * gsvcdesc = _T("TS2 Dept. LE10 Team");
const xch * gldbname = _T("wwrdb.db");
      u16   grdbport = 2013;

const xch * gcreatetbl_member = 
    _T("CREATE TABLE [member] (")
    _T("[wwkey] INTEGER, ")
    _T("[uid] CHAR(20) NOT NULL DEFAULT '********************', ")
    _T("[name] CHAR DEFAULT 'Invalid', ")
    _T("[position] INT DEFAULT 1, ")
    _T("[duty] INT DEFAULT 10, ")
    _T("[dept] CHAR DEFAULT 'Invalid', ")
    _T("[team] CHAR DEFAULT 'Invalid', ")
    _T("[yyyymmdd] DATE DEFAULT '2000-01-01', ")
    _T("[birthday] CHAR(4) DEFAULT '0101', ")
    _T("[solar] BOOL(1) DEFAULT 1, ")
    _T("[phone] CHAR DEFAULT '000-0000-0000', ")
    _T("[userid] CHAR DEFAULT 'Invalid', ")
    _T("[usergroup] CHAR DEFAULT 'Invalid', ")
    _T("[grouptype] BOOL(1) DEFAULT 0, ")
    _T("[wwmail] CHAR DEFAULT 'Invalid', ")
    _T("[regidate] DATE DEFAULT '2000-01-01', ")
    _T("[address] CHAR DEFAULT 'Invalid', ")
    _T("[customkey] CHAR DEFAULT 'Invalid', ")
    _T("[custommail] CHAR DEFAULT 'Invalid', ")
    _T("CONSTRAINT [] PRIMARY KEY ([wwkey]));");

const xch * gcreatetbl_commute = 
    _T("CREATE TABLE [commute] (")
    _T("[wwkey] INTEGER DEFAULT 0, ")
    _T("[indexer] INTEGER DEFAULT (-1), ")      // record key
    _T("[ltime] INT64(1) DEFAULT 0, ")
    _T("[time] INT64(1) DEFAULT 0, ")
    _T("[mode] INT(1) DEFAULT 100, ")             // session event
    _T("[state] INT(1) DEFAULT 0, ")             // 
    _T("[changed] BOOL(1) DEFAULT 0, ")
    _T("[confirm] BOOL(1) DEFAULT 0, ")
    _T("[userid] CHAR DEFAULT 'Invalid', ")
    _T("[ctime] INT64(1) DEFAULT 0, ")
    _T("[comment] CHAR DEFAULT '');");

const xch * gcreatetbl_fileinfo =
    _T("CREATE TABLE[fileinfo](")
    _T("[name] CHAR NOT NULL DEFAULT invalid, ")
    _T("[type] INT NOT NULL DEFAULT 0, ")
    _T("[major] INT NOT NULL DEFAULT 0, ")
    _T("[minor] INT NOT NULL DEFAULT 0, ")
    _T("[bdate] INT NOT NULL DEFAULT 0, ")
    _T("[bnum] INT NOT NULL DEFAULT 0);");

const xch * gcheck_ldb =
    _T("SELECT name FROM sqlite_master WHERE type='table' and name = 'commute';");

#   if defined(l3platform_winapi)
bl getconinfo(void)
{
    u32 getword = 0;
    bl ret = bfalse;
    ret = l3Getu32FromRegistry(HKEY_LOCAL_MACHINE, _T("SoftWare\\l3Platform\\Wisewires"), _T("wwsport"), getword );

    if(ret)
        grdbport = (u16)getword;
    _userchk("getconinfo ret:%d / port:%d", ret, grdbport);
    return ret;
}
#   endif // defined(l3platform_winapi)

l3rdbserver * gprdbsvr = pnull;
#   if defined(l3platform_winapi)
void l3svchandler(l3svcstate_e status, u32 ctl, u32 evt, void * eventdata, void * pobj)
{
    (void)eventdata;
    (void)pobj;
    _trace("l3svccb status:%d ctl:%d evt:%d obj:%d", status, ctl, evt, pobj);
    switch(status)
    {
    case l3svcstate_state:
        _trace("l3svcstate_state");
        break;
    case l3svcstate_start:
        _trace("l3svcstate_start");
#if defined(l3feature_loggertrace)
#   if defined(l3platform_winapi)
        l3xstrcpy(l3logger::mpath, l3service::msvc.mmodulepath);
        l3xstrcat(l3logger::mpath, _T("\\wws"));
#   else
        l3xstrcpy(l3logger::mpath, _T("/wws"));
#   endif
        l3loggerset(l3lgr_crt | l3lgr_file);
#endif
        {
            l3database ldb;
            l3queryset qset;
            qset.statement(gcheck_ldb);
            ldb.mdbname = l3service::msvc.mmodulepath;
            ldb.mdbname += _T("\\");
            ldb.mdbname += gldbname;
            ldb.open();
            ldb.select(qset);
            if(!qset.mnr)
            {
                _trace("database not exist. create now.");
                qset.statement(gcreatetbl_commute);
                ldb.exec(qset);
                qset.statement(gcreatetbl_member);
                ldb.exec(qset);
                qset.statement(gcreatetbl_fileinfo);
                ldb.exec(qset);
            }
            ldb.close();
        }
        gprdbsvr = new l3rdbserver;
        gprdbsvr->mdbname = l3service::msvc.mmodulepath;
        gprdbsvr->mdbname += _T("\\");
        gprdbsvr->mdbname += gldbname;
        getconinfo();
        gprdbsvr->mport = grdbport;
        gprdbsvr->start();
        l3sprintf("Start Remote Database Server Service\n");
        break;
    case l3svcstate_pause:
        _trace("l3svcstate_pause");
        break;
    case l3svcstate_continue:
        _trace("l3svcstate_continue");
        break;
    case l3svcstate_stop:
        _trace("l3svcstate_stop");
        if(gprdbsvr)
        {
            gprdbsvr->stop();
            delete gprdbsvr;
            gprdbsvr = pnull;
            l3sprintf("Stop Remote Database Server Service\n");
        }
        break;
    default:
        break;
    }
}
#   else // defined(l3platform_winapi)
void l3svchandler(l3svcstate_e status, void * pobj)
{
    _trace("l3svccb status:%d obj:%p", status, pobj);
    switch(status)
    {
    case l3svcstate_start:
        _trace("l3svcstate_start");
#if defined(l3feature_loggertrace)
#   if defined(l3platform_winapi)
        l3xstrcpy(l3logger::mpath, l3service::msvc.mmodulepath);
        l3xstrcat(l3logger::mpath, _T("\\wws"));
#   else
        l3xstrcpy(l3logger::mpath, _T("/wws"));
#   endif
        l3loggerset(l3lgr_crt | l3lgr_file);
#endif
        {
            l3database ldb;
            l3queryset qset;
            qset.statement(gcheck_ldb);
            ldb.mdbname = gldbname;
            ldb.open();
            ldb.select(qset);
            if(!qset.mnr)
            {
                _trace("database not exist. create now.");
                qset.statement(gcreatetbl_commute);
                ldb.exec(qset);
                qset.statement(gcreatetbl_member);
                ldb.exec(qset);
                qset.statement(gcreatetbl_fileinfo);
                ldb.exec(qset);
            }
            ldb.close();
        }
        gprdbsvr = new l3rdbserver;
        gprdbsvr->mdbname = gldbname;
        gprdbsvr->mport = grdbport;
        gprdbsvr->start();
        break;
    case l3svcstate_stop:
        _trace("l3svcstate_stop");
        if(gprdbsvr)
        {
            gprdbsvr->stop();
            delete gprdbsvr;
            gprdbsvr = pnull;
        }
        break;
    default:
        break;
    }
}
#   endif // defined(l3platform_winapi)

#ifdef l3platform_winapi
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
#else
int main(int argc, char * argv[])
#endif
{
#ifdef l3platform_winapi
    (void)envp;
    HMODULE hModule = ::GetModuleHandle(NULL);
    if (hModule == NULL)
    {
        // TODO: change error code to suit your needs
        _tprintf(_T("Fatal Error: GetModuleHandle failed\n"));
        return 1;
    }
    // initialize MFC and print and error on failure
    if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
    {
        // TODO: change error code to suit your needs
        _tprintf(_T("Fatal Error: MFC initialization failed\n"));
        return 1;
    }
#endif

// #if defined(l3feature_loggertrace)
// #   if defined(l3platform_winapi)
//     l3xstrcpy(l3logger::mpath, l3service::msvc.mmodulepath);
//     l3xstrcat(l3logger::mpath, _T("\\wws"));
// #   else
//     l3xstrcpy(l3logger::mpath, _T("./wws"));
// #   endif
//     l3loggerset(l3lgr_crt | l3lgr_file);
// #endif

    l3sprintf("Remote Database Server Service\n");
    l3service svc;
    gprdbsvr = pnull;
    svc.setreactor(l3svchandler, (void*)-1);

#   if defined(l3platform_winapi)
    if(!svc.parameterparse(argc, argv))
    {
        l3sprintf("This is not for console execution.\n");
        return bfalse;
    }
    svc.setupsvcname(gsvcname);
    svc.setuptitlename(gsvcdisplay);
    svc.setupdescription(gsvcdesc);
#   else
    if(argc == 2 && argv[1])
    {
        grdbport = (u16)l3xstrtou32(argv[1], pnull, 10);
        l3sprintf("listening port set to %d\n", grdbport);
    }
#   endif // defined(l3platform_winapi)

    return !svc.controlservice();
}
